package cn.wjzhang.core.aspect;

import cn.wjzhang.core.beans.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import java.util.ArrayList;
import java.util.List;

/**
 * ========================
 * 数据校验
 *
 * @author wjzhang
 * @version v1.0
 * ========================
 * @date 2023/6/25 14:33
 */
@Slf4j
@Aspect
@Component
public class DataValidateAspect {

    /**
     * 目标方法的异常，一般都需要再次抛出去。让别人感知
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("execution(* cn.wjzhang..modules..*Controller.*(..))")
    public Object validAround(ProceedingJoinPoint point) throws Throwable {
        // 获取方法参数
        Object[] args = point.getArgs();
        log.debug("校验切面介入工作....");
        // 遍历方法参数，查找BindingResult对象
        BindingResult bindingResult = null;
        for (Object arg : args) {
            if (arg instanceof BindingResult) {
                bindingResult = (BindingResult) arg;
                break;
            }
        }

        // 如果存在BindingResult对象，则进行参数校验
        if (bindingResult != null) {
            if (bindingResult.hasErrors()) {
                // 处理校验错误
                // 这里可以根据具体需求进行错误处理，例如返回错误信息或者抛出异常
                // 获取所有校验错误
                List<ObjectError> errors = bindingResult.getAllErrors();

                // 创建一个用于保存错误信息的列表
                List<String> errorMessages = new ArrayList<>();

                // 遍历错误列表，提取错误信息
                for (ObjectError error : errors) {
                    errorMessages.add(error.getDefaultMessage());
                }

                return Result.error("参数校验失败", errorMessages);
//                  throw new WjException(JSONArray.toJSONString(errorMessages));
            }
        }

        log.debug("校验切面将目标方法已经放行.");
        // 继续执行被拦截的方法 就是我们反射的  method.invoke();
        return point.proceed();
    }

}